#include "ostree-repo-private.h"
#define WHITEOUT_PREFIX ".wh."
+#define OPAQUE_WHITEOUT_NAME ".wh..wh..opq"
/* Per-checkout call state/caching */
typedef struct {
GError **error)
{
gboolean did_exist = FALSE;
+ gboolean is_opaque_whiteout = FALSE;
const gboolean sepolicy_enabled = options->sepolicy && !self->disable_xattrs;
g_autoptr(GVariant) dirtree = NULL;
g_autoptr(GVariant) dirmeta = NULL;
return TRUE; /* Note early return */
}
+ if (options->process_whiteouts)
+ {
+ g_autoptr(GVariant) dir_file_contents = g_variant_get_child_value (dirtree, 0);
+ GVariantIter viter;
+ const char *fname;
+ g_autoptr(GVariant) contents_csum_v = NULL;
+ g_variant_iter_init (&viter, dir_file_contents);
+ while (g_variant_iter_loop (&viter, "(&s@ay)", &fname, &contents_csum_v))
+ {
+ is_opaque_whiteout = (g_str_equal (fname, OPAQUE_WHITEOUT_NAME));
+ if (is_opaque_whiteout)
+ break;
+ }
+ contents_csum_v = NULL; /* iter_loop freed it */
+ }
+
/* First, make the directory. Push a new scope in case we end up using
* setfscreatecon().
*/
return FALSE;
}
+ /* If it is an opaque whiteout, ensure the destination is empty first. */
+ if (is_opaque_whiteout)
+ {
+ if (!glnx_shutil_rm_rf_at (destination_parent_fd, destination_name, cancellable, error))
+ return FALSE;
+ }
+
/* Create initially with mode 0700, then chown/chmod only when we're
* done. This avoids anyone else being able to operate on partially
* constructed dirs.
# Whiteouts
cd ${test_tmpdir}
mkdir -p overlay/baz/
-if touch overlay/baz/.wh.cow && touch overlay/.wh.deeper; then
+if touch overlay/baz/.wh.cow && touch overlay/.wh.deeper && touch overlay/baz/another/.wh..wh..opq; then
touch overlay/anewfile
mkdir overlay/anewdir/
touch overlay/anewdir/blah
assert_not_has_dir overlay-co/deeper
assert_has_file overlay-co/anewdir/blah
assert_has_file overlay-co/anewfile
+ assert_not_has_file overlay-co/baz/another/y
# And test replacing a directory wholesale with a symlink as well as a regular file
mkdir overlay